package com.jrtc.backend.interceptor;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.jrtc.base.annotations.*;
import com.jrtc.base.config.LoginException;
import com.jrtc.base.config.constants.Constants;
import com.jrtc.base.entity.dto.SysUserDTO;
import com.jrtc.base.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Collection;

public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisUtil redis;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) {
        String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token

        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }

        //开发阶段
//        if(1==1){
//            return true;
//        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //检查是否有passToken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }

        //检查有没有需要用户登录的注解
        if (method.isAnnotationPresent(AdminLoginToken.class)) {
            AdminLoginToken userLoginToken = method.getAnnotation(AdminLoginToken.class);
            if (userLoginToken.required()) {
                tokenUtil(token);
                return true;
            }
        }

        //检查用户有没有权限浏览
        if (method.isAnnotationPresent(TokenQuery.class)) {
            TokenQuery userLoginToken = method.getAnnotation(TokenQuery.class);
            if (userLoginToken.required()) {
                Integer permission = getPermission(token);
                if (permission == 1 || permission == 3 || permission == 5 || permission == 9 || permission == 17 || permission == 7 || permission == 11 || permission == 19 || permission == 13 || permission == 21 || permission == 25 || permission == 15 || permission == 23 || permission == 29 || permission == 31)
                    return true;
                else
                    throw new RuntimeException("您没有权限进行浏览");
            }
        }

        //检查用户有没有权限编辑
        if (method.isAnnotationPresent(TokenUpd.class)) {
            TokenUpd userLoginToken = method.getAnnotation(TokenUpd.class);
            if (userLoginToken.required()) {
                Integer permission = getPermission(token);
                if (permission == 2 || permission == 3 || permission == 6 || permission == 10 || permission == 18 || permission == 7 || permission == 11 || permission == 19 || permission == 14 || permission == 22 || permission == 26 || permission == 15 || permission == 23 || permission == 30 || permission == 31)
                    return true;
                else
                    throw new RuntimeException("您没有权限进行编辑");
            }
        }

        //检查用户有没有权限删除
        if (method.isAnnotationPresent(TokenDel.class)) {
            TokenDel userLoginToken = method.getAnnotation(TokenDel.class);
            if (userLoginToken.required()) {
                Integer permission = getPermission(token);
                if (permission == 4 || permission == 5 || permission == 6 || permission == 12 || permission == 20 || permission == 7 || permission == 13 || permission == 21 || permission == 14 || permission == 22 || permission == 28 || permission == 15 || permission == 23 || permission == 29 || permission == 30 || permission == 31)
                    return true;
                else
                    throw new RuntimeException("您没有权限进行删除");
            }
        }

        //检查用户有没有权限提交
        if (method.isAnnotationPresent(TokenAdd.class)) {
            TokenAdd userLoginToken = method.getAnnotation(TokenAdd.class);
            if (userLoginToken.required()) {
                Integer permission = getPermission(token);
                if (permission == 8 || permission == 9 || permission == 10 || permission == 12 || permission == 24 || permission == 11 || permission == 13 || permission == 25 || permission == 14 || permission == 26 || permission == 28 || permission == 15 || permission == 29 || permission == 30 || permission == 31)
                    return true;
                else
                    throw new RuntimeException("您没有权限进行提交");
            }
        }

        //检查用户有没有权限审核
        if (method.isAnnotationPresent(TokenCheck.class)) {
            TokenCheck userLoginToken = method.getAnnotation(TokenCheck.class);
            if (userLoginToken.required()) {
                Integer permission = getPermission(token);
                if (permission == 16 || permission == 17 || permission == 18 || permission == 20 || permission == 24 || permission == 19 || permission == 21 || permission == 25 || permission == 22 || permission == 26 || permission == 28 || permission == 23 || permission == 29 || permission == 30 || permission == 31)
                    return true;
                else
                    throw new RuntimeException("您没有权限进行审核");
            }
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
    }

    private String tokenUtil(String token) {
        // 执行认证
        if (token == null) {
            throw new RuntimeException("无有效token，请重新登录");
        }
        Collection<String> keys = redis.keys(Constants.DOCTOR_LOGIN_TOKEN_KEY.getValue() + "*" + token);//根据唯一的token查询出唯一key
        if (keys == null || keys.size() < 1)
            throw new LoginException("登录已过期，请重新登录");
        // redis key
        String account = "";
        for (String item : keys)
            account = item;

        //从redis中获取token ip信息进行验证
        String objectMap = redis.get(account).toString();
        if (objectMap == null) {
            throw new RuntimeException("无有效token，请重新登录");
        }

        //每操作一次，从新往redis中存一次刷新时间
        redis.set(account, objectMap, 60 * 60 * 24 * 3);

        return objectMap;
    }

    public Integer getPermission(String token) {
        String json = tokenUtil(token);
        return JSON.parseObject(json, SysUserDTO.class).getPermission();
    }
}
